package backpage.task;

import backpage.entity.*;
import backpage.entity.po.CompoffApply;
import backpage.entity.po.OvertimeApply;
import backpage.mapper.SalaryDetailsMapper;
import backpage.mapper.SalarySummaryMapper;
import backpage.service.EmployeeService;
import backpage.service.IOvertimeApplyService;
import backpage.service.ICompoffApplyService;
import backpage.service.SalarySummaryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

@Component
public class SalarySummaryScheduler {

    @Autowired
    private SalarySummaryService salarySummaryService;

    @Autowired
    private IOvertimeApplyService overtimeApplyService;

    @Autowired
    private ICompoffApplyService compoffApplyService;

    @Autowired
    private SalarySummaryMapper salarySummaryMapper;

    @Autowired
    private SalaryDetailsMapper salaryDetailsMapper;

    // 每个月的第一天的 0 点执行任务
    @Scheduled(cron = "0 0 0 1 * ?")
    public void createMonthlySalarySummary() {
        salarySummaryService.createMonthlySalarySummary();
    }

    @Scheduled(cron = "0 0 0 * * ?")
    public void calculateOvertimeAndCompoff() {
        // 获取当前时间
        Calendar now = Calendar.getInstance();
        Date endDate = now.getTime();

        // 获取前一天的开始时间（00:01:00）
        now.add(Calendar.DAY_OF_MONTH, -1);
        now.set(Calendar.HOUR_OF_DAY, 0);
        now.set(Calendar.MINUTE, 1);
        now.set(Calendar.SECOND, 0);
        now.set(Calendar.MILLISECOND, 0);
        Date startDate = now.getTime();

        // 获取当月第一天
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        Date month = calendar.getTime();

        // 处理加班信息
        processOvertimeApplies(startDate, endDate, month);

        // 处理调休信息
        processCompoffApplies(startDate, endDate, month);
    }

    /**
     * 处理加班申请信息
     */
    public void processOvertimeApplies(Date startDate, Date endDate, Date month) {
        // 获取已批准的加班申请
        List<OvertimeApply> overtimeApplies = overtimeApplyService.getApprovedOvertimeApplies(startDate, endDate);

        for (OvertimeApply overtimeApply : overtimeApplies) {
            // 获取员工当月薪资汇总信息
            SalarySummary salarySummary = salarySummaryMapper.selectByEmployeeIdAndMonth(
                    Long.valueOf(overtimeApply.getEmployeeId()), month);

            // 计算加班有效时长
            BigDecimal overtimeHours = calculateOvertimeHours(
                    overtimeApply.getStartTime(), overtimeApply.getEndTime(), overtimeApply.getType());

            // 计算加班工资
            BigDecimal amount = overtimeHours.multiply(salarySummary.getHourPay());

            // 更新薪资汇总表的加班工资
            salarySummary.setOvertimePay(salarySummary.getOvertimePay().add(amount));
            salarySummaryMapper.update(salarySummary);

            // 插入薪资明细表
            SalaryDetails salaryDetails = new SalaryDetails(
                    0L, salarySummary.getId(), 1, overtimeApply.getId(), amount, "加班工资");
            salaryDetailsMapper.insertSalaryDetails(salaryDetails);
        }
    }

    /**
     * 处理调休申请信息
     */
    public void processCompoffApplies(Date startDate, Date endDate, Date month) {
        // 获取已批准的调休申请
        List<CompoffApply> compoffApplies = compoffApplyService.getApprovedCompoffApplies(startDate, endDate);

        for (CompoffApply compoffApply : compoffApplies) {
            // 获取员工当月薪资汇总信息
            SalarySummary salarySummary = salarySummaryMapper.selectByEmployeeIdAndMonth(
                    Long.valueOf(compoffApply.getEmployeeId()), month);

            // 计算调休时长
            BigDecimal compoffHours = calculateCompoffHours(compoffApply.getStartTime(), compoffApply.getEndTime());

            // 计算调休扣款
            BigDecimal amount = compoffHours.multiply(salarySummary.getHourPay());

            // 更新薪资汇总表的调休扣款
            salarySummary.setCompoffPay(salarySummary.getCompoffPay().add(amount));
            salarySummaryMapper.update(salarySummary);

            // 插入薪资明细表
            SalaryDetails salaryDetails = new SalaryDetails(
                    0L, salarySummary.getId(), 2, compoffApply.getId(), amount, "调休扣钱");
            salaryDetailsMapper.insertSalaryDetails(salaryDetails);
        }
    }

    // 计算加班总时间
    private BigDecimal calculateOvertimeHours(Date startTime, Date endTime, Integer type) {
        Calendar startCal = Calendar.getInstance();
        startCal.setTime(startTime);
        Calendar endCal = Calendar.getInstance();
        endCal.setTime(endTime);

        // 判断是否为同一天
        boolean isSameDay = startCal.get(Calendar.YEAR) == endCal.get(Calendar.YEAR) &&
                startCal.get(Calendar.DAY_OF_YEAR) == endCal.get(Calendar.DAY_OF_YEAR);

        double totalHours = 0.0;

        if (isSameDay) {
            // 同一天的情况
            long diffMillis = endTime.getTime() - startTime.getTime();
            double hours = (double) diffMillis / (1000 * 60 * 60);
            // 不足1小时按1小时计算
            totalHours = Math.ceil(hours);
        } else {
            // 不是同一天的情况

            // 处理第一天
            Calendar firstDayEnd = (Calendar) startCal.clone();
            firstDayEnd.set(Calendar.HOUR_OF_DAY, 18);
            firstDayEnd.set(Calendar.MINUTE, 0);
            firstDayEnd.set(Calendar.SECOND, 0);

            // 如果设置的结束时间小于开始时间，则不计算第一天的加班
            if (firstDayEnd.getTimeInMillis() <= startCal.getTimeInMillis()) {
                totalHours += 0;
            } else {
                long firstDayMillis = firstDayEnd.getTimeInMillis() - startCal.getTimeInMillis();
                double firstDayHours = (double) firstDayMillis / (1000 * 60 * 60);
                // 不足1小时按1小时计算
                firstDayHours = Math.ceil(firstDayHours);

                // 如果开始时间小于12点，减去2小时
                if (startCal.get(Calendar.HOUR_OF_DAY) < 12) {
                    firstDayHours = Math.max(0, firstDayHours - 2);
                }

                totalHours += firstDayHours;
            }

            // 处理中间完整的天数
            Calendar tempCal = (Calendar) startCal.clone();
            tempCal.add(Calendar.DAY_OF_YEAR, 1);

            while (tempCal.get(Calendar.YEAR) < endCal.get(Calendar.YEAR) ||
                    tempCal.get(Calendar.DAY_OF_YEAR) < endCal.get(Calendar.DAY_OF_YEAR)) {
                totalHours += 8; // 中间每天按8小时计算
                tempCal.add(Calendar.DAY_OF_YEAR, 1);
            }

            // 处理最后一天
            Calendar lastDayStart = (Calendar) endCal.clone();
            lastDayStart.set(Calendar.HOUR_OF_DAY, 0);
            lastDayStart.set(Calendar.MINUTE, 0);
            lastDayStart.set(Calendar.SECOND, 0);

            long lastDayMillis = endCal.getTimeInMillis() - lastDayStart.getTimeInMillis();
            double lastDayHours = (double) lastDayMillis / (1000 * 60 * 60);
            // 不足1小时按1小时计算
            lastDayHours = Math.ceil(lastDayHours);

            // 如果结束时间小于12点，减去2小时
            if (endCal.get(Calendar.HOUR_OF_DAY) < 12) {
                lastDayHours = Math.max(0, lastDayHours - 2);
            }

            totalHours += lastDayHours;
        }

        // 根据type进行倍数计算
        if (type == 3) {
            totalHours *= 3;
        } else {
            totalHours *= 2;
        }

        return BigDecimal.valueOf(totalHours).setScale(2, RoundingMode.HALF_UP);
    }

    // 计算调休总时间
    private BigDecimal calculateCompoffHours(Date startTime, Date endTime) {
        Calendar startCal = Calendar.getInstance();
        startCal.setTime(startTime);
        Calendar endCal = Calendar.getInstance();
        endCal.setTime(endTime);

        // 判断是否为同一天
        boolean isSameDay = startCal.get(Calendar.YEAR) == endCal.get(Calendar.YEAR) &&
                startCal.get(Calendar.DAY_OF_YEAR) == endCal.get(Calendar.DAY_OF_YEAR);

        double totalHours = 0.0;

        if (isSameDay) {
            // 同一天的情况
            totalHours += calculateValidHoursInDay(startCal, endCal);
        } else {
            // 不是同一天的情况

            // 处理第一天
            Calendar firstDayEnd = (Calendar) startCal.clone();
            firstDayEnd.set(Calendar.HOUR_OF_DAY, 18);
            firstDayEnd.set(Calendar.MINUTE, 0);
            firstDayEnd.set(Calendar.SECOND, 0);

            totalHours += calculateValidHoursInDay(startCal, firstDayEnd);

            // 处理中间完整的天数
            Calendar tempCal = (Calendar) startCal.clone();
            tempCal.add(Calendar.DAY_OF_YEAR, 1);

            while (tempCal.get(Calendar.YEAR) < endCal.get(Calendar.YEAR) ||
                    tempCal.get(Calendar.DAY_OF_YEAR) < endCal.get(Calendar.DAY_OF_YEAR)) {
                // 中间每天按8小时计算（4小时上午 + 4小时下午）
                totalHours += 8;
                tempCal.add(Calendar.DAY_OF_YEAR, 1);
            }

            // 处理最后一天
            Calendar lastDayStart = (Calendar) endCal.clone();
            lastDayStart.set(Calendar.HOUR_OF_DAY, 8);
            lastDayStart.set(Calendar.MINUTE, 0);
            lastDayStart.set(Calendar.SECOND, 0);

            totalHours += calculateValidHoursInDay(lastDayStart, endCal);
        }

        // 限制最大为8小时
        if (totalHours > 8) {
            totalHours = 8;
        }

        return BigDecimal.valueOf(totalHours).setScale(2, RoundingMode.HALF_UP);
    }

    // 计算一天内有效时间段的小时数
    private double calculateValidHoursInDay(Calendar start, Calendar end) {
        double hours = 0.0;

        // 上午时段 8:00-12:00
        Calendar morningStart = (Calendar) start.clone();
        morningStart.set(Calendar.HOUR_OF_DAY, 8);
        morningStart.set(Calendar.MINUTE, 0);
        morningStart.set(Calendar.SECOND, 0);

        Calendar morningEnd = (Calendar) start.clone();
        morningEnd.set(Calendar.HOUR_OF_DAY, 12);
        morningEnd.set(Calendar.MINUTE, 0);
        morningEnd.set(Calendar.SECOND, 0);

        // 计算上午有效时间
        hours += calculateOverlapHours(start, end, morningStart, morningEnd);

        // 下午时段 14:00-18:00
        Calendar afternoonStart = (Calendar) start.clone();
        afternoonStart.set(Calendar.HOUR_OF_DAY, 14);
        afternoonStart.set(Calendar.MINUTE, 0);
        afternoonStart.set(Calendar.SECOND, 0);

        Calendar afternoonEnd = (Calendar) start.clone();
        afternoonEnd.set(Calendar.HOUR_OF_DAY, 18);
        afternoonEnd.set(Calendar.MINUTE, 0);
        afternoonEnd.set(Calendar.SECOND, 0);

        // 计算下午有效时间
        hours += calculateOverlapHours(start, end, afternoonStart, afternoonEnd);

        return hours;
    }

    // 计算两个时间段的重叠小时数
    private double calculateOverlapHours(Calendar start1, Calendar end1, Calendar start2, Calendar end2) {
        // 如果两个时间段没有重叠，返回0
        if (start1.after(end2) || end1.before(start2)) {
            return 0;
        }

        // 计算重叠开始时间
        Calendar overlapStart = (Calendar) start1.clone();
        if (start2.after(start1)) {
            overlapStart = (Calendar) start2.clone();
        }

        // 计算重叠结束时间
        Calendar overlapEnd = (Calendar) end1.clone();
        if (end2.before(end1)) {
            overlapEnd = (Calendar) end2.clone();
        }

        // 计算重叠时长（小时）
        long diffMillis = overlapEnd.getTimeInMillis() - overlapStart.getTimeInMillis();
        double hours = (double) diffMillis / (1000 * 60 * 60);

        // 不足1小时按1小时计算
        return Math.ceil(hours);
    }

}